home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
shadowlib.lha
/
shadow
/
Examples
/
Source
/
PerformanceTests.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-13
|
59KB
|
2,100 lines
/*
* These used to be compile-time options to Browser.
*
* Obviously this makes no sense for public code, so I have
* stuck all of that here.
*
* Makes Browser less unintelligble :^/
*
* (C) Copyright 1991 David C. Navas
*/
#include <shadow/coreMeta.h>
#include <shadow/coreRoot.h>
#include <shadow/process.h>
#include <shadow/semaphore.h>
#include <ipc.h>
#include <ipc_proto.h>
#include <shadow/shadow_proto.h>
#include <shadow/shadow_pragmas.h>
#include <shadow/method.h>
#include <dos/dostags.h>
#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>
#include <proto/exec.h>
#include <math.h>
extern struct ExecBase * __far SysBase;
struct Library * __far IPCBase;
struct ShadowBase * __far ShadowBase;
struct DosLibrary * __far DOSBase;
/*
* To test the binary tree speed.
*/
void BinSpeedTest(void);
/*
* To test the memory speed.
*/
void MemorySpeedTest(void);
void MemorySpeedTest2(void);
/*
* To test the semaphore speed.
*/
void SemaphoreSpeedTest(void);
/*
* To test the FindString() speed.
*/
void StringSpeedTest(void);
/*
* This is for the method testing and patching/attribute tests.
*/
#define DOS_PROCESS_CLASS "dos process class"
#define NEW_SUPER_CLASS "testing new superclass!"
#define FAKE_DOS_TASK "Fake dos Task"
#define PROCESS_TASK "testing subprocess..."
#define TEST_PORT_NAME "My perftesting port"
#define METH_TEST_SPEED "Method Tst5"
#define METH_TEST_PROC1 "Method test SHADOW_MSG_PREPROC"
#define METH_TEST_PROC2 "Method test SHADOW_MSG_NEVER_PREPROC"
#define METH_TEST_PORT "Method test send to PORT type"
#define METH_TEST_SEM1 "Method test semaphore1"
#define METH_TEST_SEM2 "Method test semaphore2"
#define METH_TEST_SPEC1 "Method test Spec Process"
#define METH_TEST_SPEC2 "Method test Spec Class"
#define METH_TEST_SPEC3 "Method test Spec Port"
#define METH_TEST_SPEC4 "Method test Spec Process II"
#define METH_TEST_SPEC5 "Method test Spec Class II"
#define METH_TEST_SPEC6 "Method test Spec Port II"
#define METH_NEW_SUPER "Method testing new superclass?"
struct MethodInvokeSpec spec1 = {
PROCESS_TASK,
PROCESS_CLASS,
META_CLASS,
SPEC_SAVE_BINDING
},
spec2 = {
NULL,
PROCESS_CLASS,
META_CLASS,
SPEC_SAVE_BINDING
},
spec3 = {
TEST_PORT_NAME,
NULL,
NULL,
SPEC_SAVE_BINDING
};
struct MethodInvokeSpec spec4 = {
FAKE_DOS_TASK,
DOS_PROCESS_CLASS,
META_CLASS,
NULL
},
spec5 = {
NULL,
DOS_PROCESS_CLASS,
META_CLASS,
NULL
},
spec6 = {
TEST_PORT_NAME,
NULL,
NULL,
NULL
};
extern ARGUMENT_TAG REF_TestMethod[],
REF_SendTestMethod[],
REF_SendTest5Method[];
long TestMethod(METHOD_ARGS, char *), SendTestMethod(METHOD_ARGS,
OBJECT testObject);
long Test5Method(METHOD_ARGS), SendTest5Method(METHOD_ARGS, OBJECT);
void ProcTestMethod(METHOD_ARGS);
void TestSemMethod(METHOD_ARGS);
void __saveds TestSem2Method(METHOD_ARGS);
#define SPEEDTESTNUMBER 100000
/*
* The Process shutdown test.
*/
METHOD_TAG procMethods[] = {
{
METH_REMOVE,
NULL, NULL,
INVOKE_FORCE_SYNC,
METH_FLAG_OBJECT_AS_DEST | METH_FLAG_NO_RTRN,
0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
TAG_END
};
/*
* Class that is to be run by "testing subprocess..."
*/
/*
* These methods are called by this test program in main()
*/
METHOD_TAG methods2[] =
{
{
"Method TEST",
NULL, NULL,
INVOKE_SYNC,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)SendTestMethod,
REF_SendTestMethod
},
{
METH_TEST_SPEED,
NULL, NULL,
INVOKE_SYNC,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)SendTest5Method,
REF_SendTest5Method
},
{
METH_TEST_PROC1,
NULL, NULL,
INVOKE_FORCE_SYNC,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
{
METH_TEST_PROC2,
NULL, NULL,
INVOKE_FORCE_SYNC|INVOKE_IGNORE_PROCESS,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
#define TEST_PORT_NUM 4
{
METH_TEST_PORT,
NULL, NULL,
INVOKE_FORCE_ASYNC,
METH_FLAG_PORT, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
{
METH_TEST_SEM1,
NULL, NULL,
INVOKE_CALL,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)TestSemMethod, NULL
},
{
METH_TEST_SEM2,
NULL, NULL,
INVOKE_FORCE_ASYNC,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)TestSem2Method, NULL
},
{
METH_TEST_SPEC1,
&spec1, NULL,
INVOKE_FORCE_SYNC,
METH_FLAG_OBJECT | METH_FLAG_SPEC, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
{
METH_TEST_SPEC2,
&spec2, NULL,
INVOKE_FORCE_SYNC,
METH_FLAG_CLASS | METH_FLAG_SPEC, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
{
METH_TEST_SPEC3,
&spec3, NULL,
INVOKE_FORCE_ASYNC,
METH_FLAG_PORT | METH_FLAG_SPEC, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
{
METH_TEST_SPEC4,
&spec4, NULL,
INVOKE_FORCE_SYNC,
METH_FLAG_OBJECT | METH_FLAG_SPEC, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
{
METH_TEST_SPEC5,
&spec5, NULL,
INVOKE_FORCE_SYNC,
METH_FLAG_CLASS | METH_FLAG_SPEC, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
{
METH_TEST_SPEC6,
&spec6, NULL,
INVOKE_FORCE_ASYNC,
METH_FLAG_PORT | METH_FLAG_SPEC, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
TAG_END
},
newMethods[] =
{
{
METH_NEW_SUPER,
NULL, NULL,
INVOKE_CALL,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)ProcTestMethod, NULL
},
TAG_END
};
struct TestDefaultAttribute
{
long thing;
};
ATTRIBUTE_TAG attrs2[] =
{
{
"A default attribute",
sizeof(struct TestDefaultAttribute),
NULL
},
TAG_END
};
/*
* Class that is to be run by the "Fake dos Process..."
*/
/*
* These are the methods that are called in the inner loop by the
* methods defined above.
*/
METHOD_TAG methods[] =
{
{
"Method TEST",
NULL, NULL,
INVOKE_SYNC,
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)TestMethod, REF_TestMethod
},
{
METH_TEST_SPEED,
NULL, NULL,
INVOKE_CALL, /* Edit this one! */
METH_FLAG_OBJECT, 0,
(METHODFUNCTYPE)Test5Method, NULL
},
TAG_END
};
/*
* The patches
*/
extern double PreTestMethod(METHOD_ARGS);
METHOD_TAG preMethod =
{
"Method TEST",
NULL, NULL,
INVOKE_SYNC,
METH_FLAG_CHECK_CONTINUE |
METH_FLAG_CLASS | METH_FLAG_NO_RTRN,
1, /* The priority */
(METHODFUNCTYPE)PreTestMethod, NULL
};
extern long PostTestMethod(METHOD_ARGS);
METHOD_TAG postMethod =
{
"Method TEST",
NULL, NULL,
INVOKE_SYNC,
METH_FLAG_OBJECT | METH_FLAG_NO_RTRN, -1,
(METHODFUNCTYPE)PostTestMethod, NULL
};
/*
* A default attribute, just to show you how they work.
*/
struct TestDefaultAttribute theDefAtt = {0xFEED};
/*
* Here, we not only test the default attribute, but we show that you
* can give a new class a default attribute for an attribute of the new
* class' superclass.
*/
ATTRIBUTE_TAG attrs[] =
{
{
"A default attribute",
sizeof(struct TestDefaultAttribute),
&theDefAtt
},
TAG_END
};
/*
* Lattice, go away.
*/
long CXBRK(void)
{
return(0);
}
/*
* really.
*/
chkabort(void)
{
return(0);
}
/*
* Some memory allocation routines. Dunno why we have these here...
*/
/*
void * __regargs temporaryAlloc(struct MemoryList *list)
{
return AllocMem(32 * list->memlst_size + sizeof(struct MemoryNode),
MEMF_PUBLIC);
}
void __regargs temporaryFree(struct MemoryList *list,
struct MemoryNode *node)
{
FreeMem(node, 32 * list->memlst_size + sizeof(struct MemoryNode));
}
*/
/*
* Possible test constants
*/
#define MEMORYTEST "MEMORY"
#define SPEEDTEST "METHOD"
#define FEATURETEST "TEST"
#define AVLTREETEST "AVL"
#define SEMTEST "SEMAPHORE"
#define STRINGTEST "STRING"
#define MEMORYTEST_VAL 1
#define SPEEDTEST_VAL 2
#define FEATURETEST_VAL 4
#define AVLTREETEST_VAL 8
#define SEMTEST_VAL 16
#define STRINGTEST_VAL 32
void main(long argc, char *argv[])
{
CLASS root,
dosTaskClass,
testClass,
dosClass,
proc,
newSuperClass;
OBJECT procObject,
testObject,
dosTask,
dosObject,
preObject,
postObject;
ULONG args[10], test = 0, i;
if (!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37)))
{
DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
Write(Output(), "Sorry, use 2.0\n", 15);
CloseLibrary(DOSBase);
return;
}
if (argc == 0)
{
VPrintf("Run this from the Shell\n", NULL);
CloseLibrary(DOSBase);
return;
}
if ((argc == 1) || !stricmp(argv[1], "?"))
{
VPrintf("\nOkay, this is how you want to run this program:\n\t%s ",
(ULONG *)&argv[0]);
VPrintf(MEMORYTEST"/S,"SPEEDTEST"/S,"FEATURETEST"/S,"
AVLTREETEST"/S,"SEMTEST"/S,"STRINGTEST"/S\n\n", NULL);
CloseLibrary(DOSBase);
return;
}
for(i = 1; i < argc; i++)
{
if (!stricmp(argv[i], MEMORYTEST))
test |= MEMORYTEST_VAL;
else
if (!stricmp(argv[i], SPEEDTEST))
test |= SPEEDTEST_VAL;
else
if (!stricmp(argv[i], FEATURETEST))
test |= FEATURETEST_VAL;
else
if (!stricmp(argv[i], AVLTREETEST))
test |= AVLTREETEST_VAL;
else
if (!stricmp(argv[i], SEMTEST))
test |= SEMTEST_VAL;
else
if (!stricmp(argv[i], STRINGTEST))
test |= STRINGTEST_VAL;
else
VPrintf("Disregarding Parameter <%s>\n", (ULONG *)&argv[i]);
}
if (!(IPCBase = OpenLibrary("ppipc.library", 0)))
{
VPrintf("requires ppipc.library in libs:\n", NULL);
CloseLibrary(DOSBase);
return;
}
if (!(ShadowBase = (struct ShadowBase *)
OpenLibrary("shadow.library", 5)))
{
VPrintf("requires shadow.library V5.x in libs:\n", NULL);
CloseLibrary(IPCBase);
CloseLibrary(DOSBase);
return;
}
if (!InitOOProgram("Performance Tester Program"))
{
CloseLibrary(IPCBase);
CloseLibrary(ShadowBase);
CloseLibrary(DOSBase);
return;
}
if (test & AVLTREETEST_VAL)
BinSpeedTest();
if (test & MEMORYTEST_VAL)
{
MemorySpeedTest();
MemorySpeedTest2();
}
if (test & SEMTEST_VAL)
SemaphoreSpeedTest();
if (test & STRINGTEST_VAL)
StringSpeedTest();
/*
* What follows below is a complete mess.
* The author realizes it, but doesn't care enough about this
* particular stretch of code to do much about it.
* Please, refer to the other examples provided for better use of
* the shadow.lib functions.
* If you like, think of this as an example of more direct mucking
* about with creating classes and objects, without
* Create[Instance|SubClass]
*/
proc = FindShadowClass(PROCESS_CLASS);
root = FindShadowClass(ROOT_CLASS);
if (test & (SPEEDTEST_VAL | FEATURETEST_VAL))
{
struct Meta *MHClass;
SetupMethodTags(procMethods, (void *)-1, (void *)-1);
dosTaskClass = DoShadow(proc, NULL, METH_SUB,
DOS_PROCESS_CLASS,
NULL,
NULL,
procMethods,
METHOD_END);
args[0] = (ULONG)proc;
args[1] = proc->ccl_size;
args[2] = (ULONG)dosTaskClass;
VPrintf("Defined procClass:<%lx> : %ld bytes :: dosProcClass:<%lx>\n",
args);
args[0] = NP_Output;
args[1] = (ULONG)Open("CONSOLE:", MODE_OLDFILE);
args[2] = TAG_END;
dosTask = DoShadow(dosTaskClass, NULL, METH_CREATE,
METHOD_END);
dosTask = DoShadow(dosTask, NULL, METH_INIT,
FAKE_DOS_TASK,
NULL,
NULL,
args,
METHOD_END);
/*
* if didn't Open, then free the resources.
*/
if (args[0] != TAG_IGNORE)
{
VPrintf("Couldn't start the Fake dos Task\n", NULL);
Close(args[1]);
}
args[0] = NP_Output;
args[1] = (ULONG)Open("CONSOLE:", MODE_OLDFILE);
args[2] = TAG_END;
procObject = DoShadow(proc, NULL, METH_CREATE, METHOD_END);
procObject = DoShadow(procObject, NULL, METH_INIT,
PROCESS_TASK,
NULL,
NULL,
args,
METHOD_END);
/*
* if didn't Open, then free the resources.
*/
if (args[0] != TAG_IGNORE)
{
VPrintf("Couldn't start the testing subprocess...", NULL);
Close(args[1]);
}
args[0] = (ULONG)procObject;
args[1] = (ULONG)dosTask;
VPrintf("Proc Objects %lx %lx\n\n", args);
SetupMethodTags(methods2, procObject, (void *)-1);
SetupMethodTags(methods, dosTask, (void *)-1);
/*
* Setup our one port test case.
*/
{
struct ShadowProcess *sp = FindAttribute(procObject,
ATTR_SHADOWPROCESS);
methods2[TEST_PORT_NUM].mtag_procObject = sp->sp_port;
}
testClass = DoShadow(root, NULL, METH_SUB,
"Test Class",
NULL,
attrs2,
methods2,
METHOD_END);
testObject = DoShadow( DoShadow(testClass,
NULL,
METH_CREATE,
METHOD_END),
NULL,
METH_INIT,
METHOD_END);
dosClass = DoShadow(testClass, NULL, METH_SUB,
"Test Class Dest",
NULL,
attrs,
methods,
METHOD_END);
dosObject = DoShadow(dosClass, NULL, METH_CREATE, METHOD_END);
if (test & FEATURETEST_VAL)
{
/*
* Well, did the attribute turn out okay?
*/
VPrintf("Default Attribute Value :: %lx\n\n",
FindAttribute(dosObject, "A default attribute"));
}
dosObject = DoShadow(dosObject, NULL, METH_INIT, METHOD_END);
AddAutoResource(NULL, UseObject(testClass), NULL);
AddAutoResource(NULL, dosTaskClass, NULL);
AddAutoResource(NULL, UseObject(dosObject), NULL);
AddAutoResource(NULL, UseObject(dosClass), NULL);
AddAutoResource(NULL, UseObject(testObject), NULL);
AddAutoResource(NULL, procObject, NULL);
AddAutoResource(NULL, UseObject(dosTask), NULL);
if (test & FEATURETEST_VAL)
{
MHClass = FindShadowClass(PATCHER_CLASS);
/*
* Add pre and post patches
*/
preMethod.mtag_procObject = dosTaskClass;
preMethod.mtag_defnObject = CurrentProcess();
preObject = DoShadow(MHClass, NULL, METH_CREATE,
METHOD_END);
preObject = DoShadow(preObject, NULL, METH_INIT,
&preMethod,
dosClass,
METHOD_END);
VPrintf("Added prePatch %lx\n", (ULONG *)&preObject);
postMethod.mtag_procObject = dosTask;
postMethod.mtag_defnObject = CurrentProcess();
postObject = DoShadow(MHClass, NULL, METH_CREATE,
METHOD_END);
postObject = DoShadow(postObject, NULL, METH_INIT,
&postMethod,
dosClass,
METHOD_END);
VPrintf("Added postPatch %lx\n", (ULONG *)&postObject);
DropObject(MHClass);
/*
* Method patching tests.
*/
VPrintf("\nMETHOD TESTING\n", NULL);
ClearShadowError();
DoShadow(testObject, NULL, "Method doesn't exist", METHOD_END);
{
double myError = GetShadowError();
VPrintf("\nMethod doesn't exist! %lx %lx\n", (ULONG *)&myError);
}
DoShadow(testObject, NULL, "Method TEST", dosObject,
METHOD_END);
DoShadow(preObject, NULL, METH_REMOVE, METHOD_END);
DropObject(preObject);
VPrintf("Removed prePatch\n\n", NULL);
DoShadow(testObject, NULL, "Method TEST", dosObject,
METHOD_END);
DoShadow(postObject, NULL, METH_REMOVE, METHOD_END);
DropObject(postObject);
VPrintf("Removed postPatch\n\n", NULL);
DoShadow(testObject, NULL, "Method TEST", dosObject,
METHOD_END);
VPrintf("\nTesting DoShadowInProcess\n", NULL);
DoShadowInProcess(dosTask, testObject, NULL, METH_TEST_PROC1,
METHOD_END);
DoShadowInProcess(dosTask, testObject, NULL, METH_TEST_PROC2,
METHOD_END);
VPrintf("\nTesting DoShadowAsync()", NULL);
DoShadowAsync(testObject, NULL, METH_TEST_PROC2, METHOD_END);
VPrintf("\nTesting PreParseShadow()\n", NULL);
{
struct IPCMessage *msg2;
msg2 = PreParseShadow(testObject, NULL, METH_TEST_PROC2,
METHOD_END);
VPrintf("Message returned = %lx\n", (ULONG *)&msg2);
ParseShadowMessage(msg2, SHADOW_RETURN_MSG_NEVER);
}
VPrintf("\nTesting METH_FLAG_PORT bit\n", NULL);
DoShadow(testObject, NULL, METH_TEST_PORT, METHOD_END);
VPrintf("\nTesting Specs\n", NULL);
DoShadow(testObject, NULL, METH_TEST_SPEC1, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC1, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC2, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC2, METHOD_END);
{
struct IPCPort *port = ServeIPCPort(TEST_PORT_NAME);
struct IPCMessage *msg;
DoShadow(testObject, NULL, METH_TEST_SPEC3, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC3, METHOD_END);
if (!port)
VPrintf("Could not create port!\n", NULL);
else
{
ShutIPCPort(port);
while(msg = GetIPCMessage(port))
ParseShadowMessage(msg, SHADOW_RETURN_MSG_NEVER);
LeaveIPCPort(port);
}
}
DoShadow(testObject, NULL, METH_TEST_SPEC4, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC4, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC5, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC5, METHOD_END);
{
struct IPCPort *port = ServeIPCPort(TEST_PORT_NAME);
struct IPCMessage *msg;
DoShadow(testObject, NULL, METH_TEST_SPEC6, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SPEC6, METHOD_END);
if (!port)
VPrintf("Could not create port!\n", NULL);
else
{
ShutIPCPort(port);
while(msg = GetIPCMessage(port))
ParseShadowMessage(msg, SHADOW_RETURN_MSG_NEVER);
LeaveIPCPort(port);
}
}
VPrintf("Trying to get to method not installed!\n", NULL);
DoShadow(testObject, NULL, METH_NEW_SUPER, METHOD_END);
SetupMethodTags(newMethods, (void *)-1, (void *)-1);
newSuperClass = DoShadow(testClass, NULL, METH_SUPER,
NEW_SUPER_CLASS,
NULL,
NULL,
&newMethods,
METHOD_END);
AddAutoResource(NULL, newSuperClass, NULL);
VPrintf("Now ----installed----\n", NULL);
DoShadow(testObject, NULL, METH_NEW_SUPER, METHOD_END);
VPrintf("METHOD TESTING DONE\n\n", NULL);
VPrintf("\n\t\t\tStarting semaphore testing\n", NULL);
DoShadow(testObject, NULL, METH_TEST_SEM2, METHOD_END);
DoShadow(testObject, NULL, METH_TEST_SEM1, METHOD_END);
}
if (test & SPEEDTEST_VAL)
{
/*
* A3000 tests under moderate system usage (many apps Open, nothing
* running) shows 40000+ for methods/sec, and 240000 for funcs/sec.
*/
DoShadow(testObject, NULL, METH_TEST_SPEED, dosObject, METHOD_END);
}
DropObject(dosObject);
DropObject(dosClass);
DropObject(testClass);
DropObject(testObject);
DropObject(dosTask);
}
DropObject(root);
DropObject(proc);
VPrintf("\n\nRemoving current program\n", NULL);
RemoveCurrentProgram(NULL);
VPrintf("Closing libraries\n", NULL);
CloseLibrary(ShadowBase);
CloseLibrary(IPCBase);
VPrintf("Attempting to purge SHADOW and PPIPC libraries.\n", NULL);
CloseLibrary(DOSBase);
/*
* Purge everything.
*/
AllocMem(-1, MEMF_ANY);
}
void BinSpeedTest(void)
{
AVLTree bt = NULL;
long i, j;
struct DateStamp ds1, ds2;
struct ClasslessObject object[256];
for(i = 0;i < 256; i++)
{
object[i].clb_class = NULL;
object[i].clb_useCount = object[i].clb_size = 0;
}
for (i = 0; i < 256; i++)
{
AddTreeNode(&bt, &object[i], i);
}
VPrintf("Beginning SHADOW AVLTree speed test of FindTreeNode:\n", NULL);
DateStamp((void *)&ds1);
for(j = 0; j < 100; j++)
{
for (i = 0; i < 256; i++)
{
FindTreeNode(&bt, i);
/*
* We don't need to call DropObject(), so don't!
* Realize, however, that you normally would want to resource
* track what it is that's returned.
*/
}
}
DateStamp((void *)&ds2);
for (i = 0; i < 256; i++)
{
RemoveTreeNode(&bt, &object[i], i);
}
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW AVLTree speed test completed.\n", NULL);
i = 50 * 25600;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld SHADOW AVLTree FindTreeNode()/second\n\n", &i);
VPrintf("Beginning SHADOW AVLTree speed test Add/Remove:\n", NULL);
DateStamp((void *)&ds1);
for(j = 0; j < 50; j++)
{
for (i = 0; i < 256; i++)
{
AddTreeNode(&bt, &object[i], i);
}
for (i = 0; i < 256; i++)
{
RemoveTreeNode(&bt, &object[i], i);
}
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW AVLTree speed test completed.\n", NULL);
i = 50 * 12800;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld SHADOW AVLTree Adds-Removes/second\n\n", &i);
}
void MemorySpeedTest(void)
{
long i, j;
void *table[128];
struct DateStamp ds1, ds2;
struct MemoryList globalMemList;
VPrintf("Beginning SHADOW memory allocation speed test:\n", NULL);
InitTable(&globalMemList, NULL, NULL, 16);
DateStamp((void *)&ds1);
for(j = 0; j < 500; j++)
{
for (i = 0; i < 128; i++)
{
table[i] = AllocateItem(&globalMemList);
}
for (i = 0; i < 128; i++)
{
FreeItem(&globalMemList, table[i]);
}
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW memory test completed.\n", NULL);
i = 50 * 64000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld SHADOW memory allocs-frees/second\n\n", &i);
/*
* A3000 tests after decent memory usage by other programs
* shows a bit over 12700 a second. (13502)
*/
VPrintf("Beginning Exec allocation speed test:\n", NULL);
DateStamp((void *)&ds1);
for(j = 0; j < 500; j++)
{
for (i = 0; i < 128; i++)
{
table[i] = AllocMem(16, MEMF_PUBLIC);
}
for (i = 0; i < 128; i++)
{
FreeMem(table[i], 16);
}
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("Exec memory test completed.\n", NULL);
i = 50 * 64000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld system memory allocs-frees/second\n\n", &i);
/*
* A3000 tests after decent memory usage by other programs
* shows a bit under 8000 a second. (7673)
*
* The comparisons are even more disparate for slightly larger
* memory block sizes. After all, very few fragments need be
* searched for blocks of 16bytes -- smallest frag. size is 8!
*/
FreeTable(&globalMemList);
}
struct MyList {
struct MyList *next;
};
void MemorySpeedTest2(void)
{
struct MyList *list1 = NULL;
struct MyList *list2;
struct MyList *temp;
struct MemoryList globalMemList;
ULONG bytes = sizeof(struct MyList);
long nodes = 10000;
long i;
VPrintf("Allocating single list...\n", NULL);
for (i = 0; i < nodes; i++) {
temp = (struct MyList *)AllocMem(bytes,NULL);
temp->next = list1;
list1 = temp;
};
VPrintf("Freeing single list...\n", NULL);
while (list1 != NULL) {
temp = list1;
list1 = list1->next;
FreeMem(temp,bytes);
};
VPrintf("Done with single list.\n", NULL);
list1 = NULL;
list2 = NULL;
VPrintf("Allocating dual lists...\n", NULL);
for (i = 0; i < nodes; i += 2) {
temp = (struct MyList *)AllocMem(bytes,NULL);
temp->next = list1;
list1 = temp;
temp = (struct MyList *)AllocMem(bytes,NULL);
temp->next = list2;
list2 = temp;
};
VPrintf("Freeing dual lists...\n", NULL);
while (list1 != NULL) {
temp = list1;
list1 = list1->next;
FreeMem(temp,bytes);
};
while (list2 != NULL) {
temp = list2;
list2 = list2->next;
FreeMem(temp,bytes);
};
VPrintf("Done with dual lists.\n", NULL);
list1 = NULL;
list2 = NULL;
InitTable(&globalMemList, NULL, NULL, bytes);
VPrintf("Allocating dual lists SHADOW...\n", NULL);
for (i = 0; i < nodes; i += 2) {
temp = (struct MyList *)AllocateItem(&globalMemList);
temp->next = list1;
list1 = temp;
temp = (struct MyList *)AllocateItem(&globalMemList);
temp->next = list2;
list2 = temp;
};
VPrintf("Freeing dual lists...\n", NULL);
while (list1 != NULL) {
temp = list1;
list1 = list1->next;
FreeItem(&globalMemList, temp);
};
while (list2 != NULL) {
temp = list2;
list2 = list2->next;
FreeItem(&globalMemList,temp);
};
VPrintf("Done with dual lists.\n", NULL);
list1 = NULL;
list2 = NULL;
FreeTable(&globalMemList);
}
void SemaphoreSpeedTest(void)
{
long i, j;
void *table[12];
char bufferNames[40][12];
struct SignalSemaphore tableSem[12];
struct DateStamp ds1, ds2;
VPrintf("Beginning SHADOW semaphore speed test:\n", NULL);
for(i = 0; i < 12; i++)
{
table[i] = (void *)lrand48();
}
DateStamp((void *)&ds1);
for(j = 0; j < 1000; j++)
{
for (i = 0; i < 12; i++)
{
PSem(table[i], SSEM_LOCK);
}
for (i = 0; i < 12; i++)
{
VSem(table[i]);
}
/*
PSem(NULL, SSEM_LOCK);
VSem(NULL);
*/
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW semaphore test completed.\n", NULL);
i = 50 * 12000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld SHADOW semaphore Psem()-VSem()/second\n\n", &i);
/*
* A3000 tests shows a bit over 8500 a second.
*/
VPrintf("Beginning SHADOW semaphore pre-allocated speed test:\n", NULL);
for (i = 0; i < 12; i++)
{
table[i] = PSem((void *)-1, SSEM_READ);
}
DateStamp((void *)&ds1);
for(j = 0; j < 1000; j++)
{
for (i = 0; i < 12; i++)
{
PSem(table[i], SSEM_READ);
}
for (i = 0; i < 12; i++)
{
VSem(table[i]);
}
}
DateStamp((void *)&ds2);
for (i = 0; i < 12; i++)
{
PSem(table[i], SSEM_DESTROY);
}
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW semaphore test completed.\n", NULL);
i = 50 * 12000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld SHADOW semaphore Pre-allocated Psem()-VSem()/second\n\n", &i);
VPrintf("Beginning Exec semaphore speed test:\n", NULL);
for(i = 0; i < 12; i++)
{
InitSemaphore(&tableSem[i]);
}
DateStamp((void *)&ds1);
for(j = 0; j < 1000; j++)
{
for (i = 0; i < 12; i++)
{
ObtainSemaphore(&tableSem[i]);
}
for (i = 0; i < 12; i++)
{
ReleaseSemaphore(&tableSem[i]);
}
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("Exec semaphore test completed.\n", NULL);
i = 50 * 12000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld System semaphore ObtainSemaphore()-"
"ReleaseSemaphore()/second\n\n", &i);
/*
* A3000 tests shows around 33,200 a second.
*/
VPrintf("Beginning Exec semaphore w/FindSemaphore() speed test:\n", NULL);
for(i = 0; i < 12; i++)
{
RawDoFmt("SHADOW #%lx", &i, SprintfCallback, bufferNames[i]);
tableSem[i].ss_Link.ln_Name = bufferNames[i];
tableSem[i].ss_Link.ln_Pri = 0;
AddSemaphore(&tableSem[i]);
}
DateStamp((void *)&ds1);
for(j = 0; j < 1000; j++)
{
for (i = 0; i < 12; i++)
{
FindSemaphore(bufferNames[i]);
ObtainSemaphore(&tableSem[i]);
}
for (i = 0; i < 12; i++)
{
ReleaseSemaphore(&tableSem[i]);
}
}
DateStamp((void *)&ds2);
for(i = 0; i < 12; i++)
{
RemSemaphore(&tableSem[i]);
}
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("Exec semaphore test w/FindSsemaphore() completed.\n", NULL);
i = 50 * 12000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld System semaphore ObtainSemaphore()-"
"ReleaseSemaphore()/second\n\n", &i);
/*
* A3000 tests shows around 7800 a second.
*/
VPrintf("Beginning Forbid()/Permit() speed test:\n", NULL);
DateStamp((void *)&ds1);
for(j = 0; j < 120000; j++)
{
Forbid();
Permit();
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("Forbid()/Permit() test completed.\n", NULL);
i = 50 * 120000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld System Forbid()-Permit()/second\n\n", &i);
/*
* A3000 tests shows a bit over 8500 a second.
*/
}
#define STRINGTESTER "Find this string in Table"
void StringSpeedTest(void)
{
long i;
struct DateStamp ds1, ds2;
VPrintf("Beginning SHADOW word-aligned FindString() speed test:\n", NULL);
UseString(STRINGTESTER);
DateStamp((void *)&ds1);
for(i = 0; i < 50000; i++)
{
FindString(STRINGTESTER);
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW FindString() test completed.\n", NULL);
i = 50 * 50000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld SHADOW FindString()/second\n\n", &i);
DropString(STRINGTESTER);
/*
* A3000 tests shows a bit under 21000 a second.
*/
VPrintf("Beginning SHADOW unaligned FindString() speed test:\n", NULL);
UseString(STRINGTESTER + 1);
DateStamp((void *)&ds1);
for(i = 0; i < 50000; i++)
{
FindString(STRINGTESTER + 1);
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW FindString() test completed.\n", NULL);
i = 50 * 50000;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld SHADOW FindString()/second\n\n", &i);
DropString(STRINGTESTER + 1);
/*
* A3000 tests shows around 17000 a second -- 15%-20% slower!.
*/
}
/*
* The speed and testing test methods.
*/
double PreTestMethod(METHOD_ARGS)
{
static long __far myLocalVar = 0; /* YES -- __far is required! */
union {
double tempD;
ULONG tempV[2];
} retval;
BPTR oldoutput;
oldoutput = SelectOutput(Open("CONSOLE:", MODE_OLDFILE));
VPrintf("Pretest called in <%s> task.\n",
(ULONG *)&(FindTask(NULL)->tc_Node.ln_Name));
if (!(retval.tempV[1] = (myLocalVar++ & 1)))
VPrintf("PreTest will block this call:\n", NULL);
oldoutput = SelectOutput(oldoutput);
Close(oldoutput);
/*
* Try to fool it into returning 100. It won't.
*/
retval.tempV[0] = 100;
return retval.tempD;
}
long PostTestMethod(METHOD_ARGS)
{
VPrintf("Post test called\n", NULL);
return 200;
}
ARGUMENT_TAG REF_TestMethod[] = {
{'JSTR', sizeof(char *), 0},
{TAG_DONE, SHADOW_RETURN_BLANK, 0}
};
long TestMethod(METHOD_ARGS, char *string)
{
long args[10];
if (!string)
string = "NULL";
args[0] = (long)MethodID;
if (!msg)
args[1] = (ULONG)"SMET";
else
args[1] = (long)&msg->ipc_Id;
args[2] = (long)FindTask(NULL)->tc_Node.ln_Name;
VPrintf("Method <%s> called via <%s> Message recv'd by task <%s>.\n", args);
args[0] = (long)class->meta_name;
args[1] = (long)object;
VPrintf("\tClass = '%s', OBJECT = '%lx'\n", args);
args[0] = (long)string;
args[1] = *(long *)(((ULONG)&string) + 4);
VPrintf("\tArgument STRING sent <%s> :: %lx\n", args);
return TRUE;
}
long Test5Method(METHOD_ARGS)
{
return TRUE;
}
ARGUMENT_TAG REF_SendTestMethod[] = {
{'JOBJ', sizeof(char *), SHADOW_OBJECT},
{TAG_DONE, SHADOW_RETURN_BLANK, 0}
};
long SendTestMethod(METHOD_ARGS, OBJECT testObject)
{
long test, args[3];
args[0] = (long)MethodID;
if (!msg)
args[1] = (ULONG)"SMET";
else
args[1] = (long)&msg->ipc_Id;
args[2] = (long)FindTask(NULL)->tc_Node.ln_Name;
VPrintf("Method <%s> called via <%s> Message recv'd by task <%s>.\n", args);
args[0] = (long)class->meta_name;
args[1] = (long)object;
VPrintf("\tClass = '%s', OBJECT = '%lx'\n", args);
args[0] = (long)testObject;
VPrintf("\tArgument OBJECT sent <%lx>\n\n", args);
test = (long)DoShadow(testObject, NULL, MethodID,
"Testing", METHOD_END);
VPrintf("Method Call first Returned %ld\n\n", &test);
test = (long)DoShadow(testObject, NULL, MethodID, METHOD_END);
VPrintf("Method Call second Returned %ld\n\n", &test);
test = (long)DoShadowAsync(testObject, NULL, MethodID, METHOD_END);
VPrintf("Method Call First Async Returned %ld\n\n", &test);
test = (long)DoShadowAsync(testObject, NULL, MethodID, METHOD_END);
VPrintf("Method Call Second Async Returned %ld\n\n", &test);
return TRUE;
}
ARGUMENT_TAG REF_SendTest5Method[] = {
{'JOBJ', sizeof(char *),SHADOW_OBJECT},
{TAG_DONE, SHADOW_RETURN_BLANK, 0}
};
long SendTest5Method(METHOD_ARGS, OBJECT testObject)
{
long i;
struct DateStamp ds1, ds2;
/*
Use this for testing the DSM() call, which is a bit faster than
DoShadow() [maybe 20% faster >50k/sec!]. Funny thing is, it makes
the function call faster too....
void *args[4];
args[0] = testObject;
args[1] = testObject->cob_class;
args[2] = METH_TEST_SPEED;
args[3] = METHOD_END;
*/
VPrintf("Beginning SHADOW method speed test:\n", NULL);
Delay(30); /* let things settle a bit */
DateStamp((void *)&ds1);
for (i = 0; i< SPEEDTESTNUMBER; i++)
{
/*
* The following would be a little bit faster than the DoShadow
* call.
* DSM(INVOKE_FIND_SELECTOR, args);
*/
DoShadow(testObject, NULL, METH_TEST_SPEED, METHOD_END);
}
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW method test completed.\n", NULL);
i = 50 * SPEEDTESTNUMBER;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld methods/second\n\n", &i);
/*
* A3000 tests under moderate system usage (many apps Open, nothing
* running) shows 40000+.
*/
VPrintf("Beginning SHADOW method synchronous message speed test:\n", NULL);
{
OBJECT procTask = FindNamedObject(PROCESS_TASK, PROCESS_CLASS,
META_CLASS);
Delay(30); /* let things settle a bit */
DateStamp((void *)&ds1);
for (i = 0; i< SPEEDTESTNUMBER/10; i++)
{
DoShadowInProcess(procTask, testObject, NULL, METH_TEST_SPEED,
METHOD_END);
}
DateStamp((void *)&ds2);
DropObject(procTask);
}
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW method test completed.\n", NULL);
i = 5 * SPEEDTESTNUMBER;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld synchronous-message methods/second\n\n", &i);
/*
* A3000 tests under moderate system usage (many apps Open, nothing
* running) shows 2500/sec
*/
VPrintf("Beginning SHADOW asynchronous-message method speed test:\n", NULL);
{
OBJECT procTask = FindNamedObject(PROCESS_TASK, PROCESS_CLASS,
META_CLASS);
Delay(30); /* let things settle a bit */
DateStamp((void *)&ds1);
for (i = 0; i< SPEEDTESTNUMBER/10; i++)
{
DoShadowInProcessAsync(procTask, testObject, NULL, METH_TEST_SPEED,
METHOD_END);
}
DateStamp((void *)&ds2);
DropObject(procTask);
}
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("SHADOW method test completed.\n", NULL);
i = 5 * SPEEDTESTNUMBER;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld asynchronous-message methods/second\n\n", &i);
/*
* A3000 tests under moderate system usage (many apps Open, nothing
* running) shows 2600/sec
*/
VPrintf("Beginning function call speed test:\n", NULL);
DateStamp((void *)&ds1);
for (i = 0; i< SPEEDTESTNUMBER; i++)
Test5Method(NULL, testObject, testObject->cob_class, METH_TEST_SPEED);
DateStamp((void *)&ds2);
ds2.ds_Tick -= ds1.ds_Tick;
ds2.ds_Minute -= ds1.ds_Minute;
if (ds2.ds_Tick < 0)
{
--ds2.ds_Minute;
ds2.ds_Tick += (60 * 50);
}
ds2.ds_Days = ds2.ds_Minute;
ds2.ds_Minute = ds2.ds_Tick / 50;
ds2.ds_Tick -= (ds2.ds_Minute * 50);
VPrintf("Function call test completed.\n", NULL);
i = 50 * SPEEDTESTNUMBER;
i = i / ((ds2.ds_Days * 60 + ds2.ds_Minute) * 50 + ds2.ds_Tick);
VPrintf("\t%ld functio calls/second\n\n", &i);
/*
* A3000 tests under moderate system usage (many apps Open, nothing
* running) shows 230000 for funcs/sec.
*/
return TRUE;
}
void ProcTestMethod(METHOD_ARGS)
{
BPTR oldoutput;
oldoutput = SelectOutput(Open("CONSOLE:", MODE_OLDFILE));
VPrintf("Called method: <%s> ", (ULONG *)&MethodID);
VPrintf("in process <%s>\n", (ULONG *)&FindTask(NULL)->tc_Node.ln_Name);
VPrintf("\tin Class <%s> ", (ULONG *)&(CurrentProcess()->cob_class->meta_name));
VPrintf(((msg)?"Asynchronously\n":"Synchronously\n"), NULL);
oldoutput = SelectOutput(oldoutput);
Close(oldoutput);
CallSuper(); /* This test is for a Remove method as well! */
}
long bang;
long cross, back;
void TestSemMethod(METHOD_ARGS)
{
VPrintf("\nStarting semaphore read tests\n", NULL);
PSem(&bang, SSEM_READ);
SetCondition(&cross, 1);
WaitCondition(&back, 1);
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("Read-Read nesting correct\n", NULL);
VSem(&bang);
} else
{
VPrintf("ERROR:Could not own a nested, single-process read semaphore\n",
NULL);
}
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Write lock while I owned a Read lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Read-Write correctly does not nest\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read-Write lock while I owned a"
" Read lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Read-RW correctly does not nest\n", NULL);
}
VSem(&bang);
VPrintf("\nStarting semaphore Write tests\n", NULL);
PSem(&bang, SSEM_WRITE);
SetCondition(&cross, 1);
WaitCondition(&back, 1);
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:owned single-process, nested, Write-Write\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly rejects Write-Write nesting\n",
NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read lock while I owned a Write lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Write-Read correctly does not nest\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read-Write lock while I owned a"
" Write lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Write-RW correctly does not nest\n", NULL);
}
VSem(&bang);
VPrintf("\nStarting semaphore ReadWrite tests\n", NULL);
PSem(&bang, SSEM_LOCK);
SetCondition(&cross, 1);
WaitCondition(&back, 1);
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("\nRW-Write nesting correct\n", NULL);
SetCondition(&cross, 1);
WaitCondition(&back, 1);
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:Got a nested Write on a RW owned semaphore\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly could not get nested Write on RW owned\n", NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("ERROR:Got a Read on a Write on a RW owned semaphore\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly could not get Read on Write on RW owned\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Got a RW on Write on a RW owned semaphore\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly could not get RW on Write on RW owned\n", NULL);
}
VSem(&bang);
} else
{
VPrintf("ERROR:Could not own a single-process write semaphore\n"
"\twhen already owned RW\n",
NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("\nRW-Read nesting correct\n", NULL);
SetCondition(&cross, 1);
WaitCondition(&back, 1);
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:Got a Write on a read on a RW owned semaphore\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly could not get Write on Read on RW owned\n", NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("Correctly got a nested Read on a RW owned semaphore\n", NULL);
VSem(&bang);
} else
{
VPrintf("ERROR: could not get a nested Read on RW owned\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Got a RW on Read on a RW owned semaphore\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly could not get RW on Read on RW owned\n", NULL);
}
VSem(&bang);
} else
{
VPrintf("ERROR:Could not own a single-process read semaphore\n"
"\twhen already owned RW\n",
NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("RW-RW nesting correct\n", NULL);
VSem(&bang);
} else
{
VPrintf("ERROR:RW nesting on single-process does not nest!\n", NULL);
}
VSem(&bang);
}
void __saveds TestSem2Method(METHOD_ARGS)
{
WaitCondition(&cross, 1);
/*
* Read locked by other process.
*/
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("Read-Read correct across processes\n", NULL);
VSem(&bang);
} else
{
VPrintf("ERROR:Could not own a multi-process read semaphore\n",
NULL);
}
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Write lock while "
"someone else owned a Read lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Read-Write correctly is not shared across processes\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read-Write lock while "
"someone else owned a Read lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Read-RW correctly is not shared across processes\n", NULL);
}
SetCondition(&back, 1);
WaitCondition(&cross, 1);
/*
* Write locked by other process.
*/
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:Write-Write owned across processes\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly rejects multiproc-WRITE ownership.\n",
NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read lock while "
"someone else owned a Write lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Write-Read correctly is not shared across processes\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a RW lock while "
"someone else owned a Write lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Write-RW correctly is not shared across processes\n", NULL);
}
SetCondition(&back, 1);
WaitCondition(&cross, 1);
/*
* Read-Write locked by other process.
*/
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:RW-Write owned across processes\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly rejects Write on RW ownership by someone else.\n",
NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read lock while "
"someone else owned a RW lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("RW-Read correctly is not shared across processes\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a RW lock while "
"someone else owned a RW lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Shared RW is correctly rejected.\n", NULL);
}
SetCondition(&back, 1);
WaitCondition(&cross, 1);
/*
* W/Read-Write locked by other process.
*/
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:RWW-Write owned across processes\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly rejects Write on RWW ownership by someone else.\n",
NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read lock while "
"someone else owned a RWW lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("RWW-Read correctly is not shared across processes\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a RW lock while "
"someone else owned a RWW lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Shared RW and RW-Write is correctly rejected.\n", NULL);
}
SetCondition(&back, 1);
WaitCondition(&cross, 1);
/*
* WR/Read-Write locked by other process.
*/
if (PSem(&bang, SSEM_WRITE|SSEM_ATTEMPT))
{
VPrintf("ERROR:RRW-Write owned across processes\n", NULL);
VSem(&bang);
} else
{
VPrintf("Correctly rejects Write on RRW ownership by someone else.\n",
NULL);
}
if (PSem(&bang, SSEM_READ|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a Read lock while "
"someone else owned a RRW lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("RRW-Read correctly is not shared across processes\n", NULL);
}
if (PSem(&bang, SSEM_LOCK|SSEM_ATTEMPT))
{
VPrintf("ERROR:Was able to own a RW lock while "
"someone else owned a RRW lock!\n",
NULL);
VSem(&bang);
} else
{
VPrintf("Shared RW and RW-Read is correctly rejected.\n", NULL);
}
SetCondition(&back, 1);
}